#pragma once

#define INITGUID

#include <list>
#include <set>
#include <d3d10.h>
#include "IEngineSystem.h"
#include "EnginePointer.h"
#include "RenderComponent.h"
#include "Model.h"
#include "ModelRenderer.h"
#include "FinalRenderer.h"
#include "GUIComponent.h"
#include "DirectionalLightRenderer.h"
#include "AmbientLightRenderer.h"
#include "SpotLightRenderer.h"
#include "PointLightRenderer.h"
#include "ICameraComponent.h"
#include "HardwareSystem.h"
#include "SceneSystem.h"
#include "SystemCollection.h"
#include "ModelLoader.h"

// {FD631EF9-7E6E-4edf-BA4B-DC9A3798CA14}
DEFINE_GUID(RENDER_SYSTEM_GUID, 
0xfd631ef9, 0x7e6e, 0x4edf, 0xba, 0x4b, 0xdc, 0x9a, 0x37, 0x98, 0xca, 0x14);

class DeferredRenderSystem : public IEngineSystem
{
public:
	DeferredRenderSystem(EnginePointer<SettingsManager>& settings, EnginePointer<IMessageQueue>& messages);
	~DeferredRenderSystem(void);

	HRESULT Initialize(EnginePointer<SystemCollection>& systems);
	void Update(LONGLONG timeElapsed);
	void DeliverMessage(Message& m);
	void Clean();
	BOOL IsClean();
	HRESULT RegisterComponent(EnginePointer<IEngineComponent>& component);
	GUID getSystemIdentifier();
	list<GUID> getDependencies();

	AUTO_SIZE;
private:
	bool graphicsLoaded;
	bool initialized;

	D3DXMATRIX projection;

	HMODULE contentModule;

	EnginePointer<HardwareSystem> hardwareSystem;
	EnginePointer<SceneSystem> sceneSystem;

	// DirectX
	EnginePointer<ID3D10Device> pDevice;
	EnginePointer<IDXGISwapChain> pSwapChain;
	EnginePointer<ID3D10EffectPool> pCommonPool;
	EnginePointer<ModelLoader> pModelLoader;
	ID3D10EffectMatrixVariable* pViewProjVariable;
	ID3D10EffectVectorVariable* pCameraPositionVariable;
	ID3D10EffectMatrixVariable* pInverseViewProjVariable;
	ID3D10EffectShaderResourceVariable* pDiffuseVariable;
	ID3D10EffectShaderResourceVariable* pNormalVariable;
	ID3D10EffectShaderResourceVariable* pDepthVariable;
	ID3D10EffectShaderResourceVariable* pDiffuseLightVariable;
	ID3D10EffectShaderResourceVariable* pSpecularLightVariable;
	ID3D10RenderTargetView* pFinalTargetView;
	ID3D10RenderTargetView* pLightTargetViews[2];
	ID3D10RenderTargetView* pObjectTargetViews[2];
	ID3D10ShaderResourceView* pDiffuseView;
	ID3D10ShaderResourceView* pDepthView;
	ID3D10ShaderResourceView* pNormalView;
	ID3D10ShaderResourceView* pDiffuseLightView;
	ID3D10ShaderResourceView* pSpecularLightView;
	ID3D10DepthStencilView* pObjectStencilView;
	ID3D10DepthStencilState* pDisabledStencilState;
	ID3D10BlendState* pLightBlendState;

	// Scene objects
	list<EnginePointer<RenderComponent>> modelComponents;
	set<EnginePointer<Model>> models;
	list<EnginePointer<GUIComponent>> guiComponents;
	EnginePointer<ICameraComponent> currentCamera;

	//Renderer
	ModelRenderer objectRenderer;
	DirectionalLightRenderer directionalRenderer;
	AmbientLightRenderer ambientRenderer;
	SpotLightRenderer spotRenderer;
	PointLightRenderer pointRenderer;
	FinalRenderer finalRenderer;

	// Initialization Functions
	HRESULT LoadGraphicsContent();
	HRESULT LoadResourceContent();
	void UnloadGraphicsContent();
	void UnloadResourceContent();
	HRESULT InitializeRenderTargets();
	HRESULT InitializeDepthBuffers();
	HRESULT InitializeStencilStates();
	HRESULT InitializeBlendStates();
};
